# 智能出行规划助手代码 (customer_service_agent_final.py 或 travel_planner_agent.py，取决于你当前运行的文件)
import json
from lazyllm import ReactAgent, fc_register, LOG, OnlineChatModule, WebModule
import requests.exceptions # 用于捕获网络请求异常
from typing import Dict, Any, List # 导入类型提示

## --- 你的 SenseCore API Key ---
SENSENOVA_API_KEY = 'sk-slRSvgQnavS9uwC35ACWcJyNofqUMKDy' # <<<<<<<<<<< 请务必在这里替换为你的真实 API Key >>>>>>>>>>>
# ------------------------------------------------
SENSENOVA_MODEL_NAME = 'Qwen3-Coder' # <<<<<<<<<<< 请务必在这里替换为你在平台开通的准确模型名称 >>>>>>>>>>>

# 模拟天气数据字典
WEATHER_DATA = {
    "北京": {
        "province": "北京市",
        "city": "北京",
        "publish_time": "2024-01-15 08:00:00",
        "weather": "晴天",
        "wind": "西北风 3-4级",
        "sunriseSunset": "日出: 07:30, 日落: 17:20",
        "temperature": "5°C / -3°C"
    },
    "上海": {
        "province": "上海市",
        "city": "上海",
        "publish_time": "2024-01-15 08:00:00",
        "weather": "阴天",
        "wind": "东南风 2-3级",
        "sunriseSunset": "日出: 07:00, 日落: 17:30",
        "temperature": "12°C / 8°C"
    },
    "广州": {
        "province": "广东省",
        "city": "广州",
        "publish_time": "2024-01-15 08:00:00",
        "weather": "雨天",
        "wind": "南风 4-5级",
        "sunriseSunset": "日出: 07:10, 日落: 18:00",
        "temperature": "18°C / 15°C"
    },
    "深圳": {
        "province": "广东省",
        "city": "深圳",
        "publish_time": "2024-01-15 08:00:00",
        "weather": "多云",
        "wind": "东风 2-3级",
        "sunriseSunset": "日出: 07:05, 日落: 17:55",
        "temperature": "20°C / 16°C"
    }
}

@fc_register("tool")
def get_weather(city: str) -> str:
    """
    天气查询工具。
    Args:
        city: 城市名（中文），当前支持北京、上海、广州、深圳。
    Returns: 当地当天的天气信息（易于LLM理解的自然语言字符串）。
    """
    LOG.info(f"Weather tool called for city: {city}")
    try:
        if city in WEATHER_DATA:
            res = WEATHER_DATA[city]
            # <<<<<<<<<<< 关键修改：直接在工具中格式化为自然语言字符串 >>>>>>>>>>>
            weather_info_str = (
                f"城市：{res['city']}，省份：{res['province']}，"
                f"发布时间：{res['publish_time']}，天气：{res['weather']}，"
                f"气温：{res['temperature']}，风力：{res['wind']}，"
                f"日出/日落：{res['sunriseSunset']}。"
            )
            return weather_info_str
        else:
            return f"抱歉，暂时无法查询到 {city} 的天气信息。目前支持的城市有：北京、上海、广州、深圳。"
    except Exception as e:
        message = f"[Tool - get_weather] error occur, city: {city}, error: {str(e)[:512]}"
        LOG.error(message)
        return message

# 定义 Agent 的角色和要求
prompt = f"""
【角色】
你是一个专业的智能出行规划助手，能够根据用户提供的城市和需求，主动查询天气信息，并结合天气情况给出详细、个性化的出行建议。

【要求】
1.  **工具调用：** 当用户询问某个城市的天气或出行建议时，你必须首先调用 `get_weather` 工具查询该城市的天气信息。
    `Action: get_weather`
    `Action Input: {{"city": "从用户问题中提取的城市名称"}}`
2.  **利用工具结果：**
    -   **在调用 `get_weather` 工具并收到其返回结果（一个包含天气信息的自然语言字符串）后，你必须直接利用这个字符串中的信息。**
    -   **从工具返回的字符串中识别出 `天气`、`气温`、`风力` 等关键信息。**
    -   **重要：在收到工具返回的天气信息后，你的下一步思考必须是整合这些信息并生成出行建议。**
3.  **生成出行建议：** 根据识别出的天气结果，结合用户的原始需求，提供具体的出行建议。
    -   **如果天气是“晴天”：** 推荐户外活动、公园、景点等，并可提及温度适宜。
    -   **如果天气是“阴天”或“多云”：** 可以推荐室内外结合的活动，或提醒可能的天气变化，建议携带外套。
    -   **如果天气是“雨天”：** 必须提醒用户携带雨具，并优先推荐室内活动，如博物馆、购物中心、咖啡馆等。
4.  **建议中包含天气概况：** 在给出建议前，先简要说明查询到的天气情况。
5.  **城市名称：** 城市名称必须是中文。
6.  **支持城市：** 目前支持查询天气的城市：{', '.join(WEATHER_DATA.keys())}。如果用户查询的城市不在支持列表中，请明确告知。
7.  **每次回复都要友好且富有条理。**

**可用工具描述：**
```json
{{
    "name": "get_weather",
    "description": "天气查询工具。根据城市名获取当地当天的天气信息。",
    "parameters": {{
        "type": "object",
        "properties": {{
            "city": {{
                "type": "string",
                "description": "城市名（中文），例如“北京”、“上海”。"
            }}
        }},
        "required": ["city"]
    }}
}}
示例交互流程：

用户：北京今天天气怎么样？有什么推荐的活动吗？
助手：思考：用户询问北京的天气和活动，需要调用 get_weather 工具。
Action: get_weather
Action Input: {{"city": "北京"}}
Observation: 城市：北京，省份：北京市，发布时间：2024-01-15 08:00:00，天气：晴天，气温：5°C / -3°C，风力：西北风 3-4级，日出/日落：日出: 07:30, 日落: 17:20。
助手：思考：我已获取北京的天气信息。天气是晴天，气温适中。我需要根据这些信息，结合用户需求，生成户外活动建议。
您好！根据查询，北京今天天气晴朗，气温在 5°C / -3°C 之间，风力西北风 3-4级。晴朗的天气非常适合户外活动！我推荐您可以：

故宫博物院： 感受历史的厚重，晴天在故宫漫步拍照非常出片。
颐和园： 皇家园林景色宜人，可以在湖边散步或划船。
奥林匹克森林公园： 享受大自然的清新空气，适合散步、跑步或骑行。 请注意保暖，早晚温差较大。
用户：广州下雨天怎么安排？
助手：思考：用户询问广州的雨天安排，需要调用 get_weather 工具。
Action: get_weather
Action Input: {{"city": "广州"}}
Observation: 城市：广州，省份：广东省，发布时间：2024-01-15 08:00:00，天气：雨天，气温：18°C / 15°C，风力：南风 4-5级，日出/日落：日出: 07:10, 日落: 18:00。
助手：思考：我已获取广州的天气信息。天气是雨天，气温较暖。我需要根据这些信息，结合用户需求，生成室内活动建议，并提醒携带雨具。
您好！根据查询，广州今天预报有雨，气温在 18°C / 15°C 之间，风力南风 4-5级。请务必携带雨具！雨天最适合的当然是室内活动了：

广东省博物馆： 了解广东的历史文化和自然遗产。
广州塔（小蛮腰）： 登高望远，即使下雨也能欣赏到独特的城市景观。
K11 购物艺术中心： 购物、餐饮、艺术展览一站式体验。
咖啡馆或书店： 找一个舒适的角落，享受阅读或品尝咖啡的悠闲时光。
"""
#初始化 LazyLLM 的 OnlineChatModule，连接 SenseCore 平台
llm_module = OnlineChatModule(
    source='sensenova',
    model=SENSENOVA_MODEL_NAME, # 使用你在 SenseCore 平台开通的准确模型名称
    api_key=SENSENOVA_API_KEY,  # 直接传入 API Key
    stream=False
)

#初始化 ReactAgent
agent = ReactAgent(
    llm=llm_module,
    tools=['get_weather'], # 注册天气查询工具
    prompt=prompt,
    stream=False,
    return_trace=False # <<<<<<<<<<< 启用 Agent 的执行轨迹追踪 >>>>>>>>>>>
)

#启动 WebModule 提供交互界面
w = WebModule(agent, port=8846, title="智能出行规划助手")

if __name__ == "main":
    # 在启动 WebModule 前进行一次简单的模型调用测试，确保 API 连接正常
    print("--- 启动前进行一次基础模型调用测试 ---")
    try:
        test_query = "你好"
        test_res = llm_module.forward(test_query)
        print(f"Test query: {test_query}")
        print(f"Test answer: {test_res}")
    except requests.exceptions.ConnectTimeout as e:
        print(f"Error calling SenseCore API (Connection Timeout): {e}")
        print("请检查你的 SENSENOVA_API_KEY 是否正确，模型是否已开通，以及网络连接是否正常。")
        exit()
    except requests.exceptions.RequestException as e:
        print(f"Error calling SenseCore API: {e}")
        print("请检查你的 SENSENOVA_API_KEY 是否正确，模型是否已开通。")
        exit()
    except Exception as e:
        print(f"An unexpected error occurred during basic chat test: {e}")
        exit()

print("--- 基础模型调用成功，启动智能出行规划助手 Web 界面 ---")
print(f"WebModule 正在启动，请访问 http://127.0.0.1:{w.port}")
w.start().wait()
